package com.gitee.hermer.boot.jee.metrice.auto.configuration;

import java.util.Collections;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.actuate.autoconfigure.EndpointCorsProperties;
import org.springframework.boot.actuate.autoconfigure.ManagementServerProperties;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping;
import org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMappingCustomizer;
import org.springframework.boot.actuate.endpoint.mvc.HealthMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MetricsMvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoint;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpointSecurityInterceptor;
import org.springframework.boot.actuate.endpoint.mvc.MvcEndpoints;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.CollectionUtils;
import org.springframework.web.cors.CorsConfiguration;

import com.gitee.hermer.boot.jee.commons.annotation.ConditionalOnLikeProperty;
import com.gitee.hermer.boot.jee.metrice.service.RedisHealthIndicator;

@Configuration                                                                                                                              
public class MetriceAutoConfiguration {

	@Bean(name = "redis")        
    @ConditionalOnMissingBean(RedisHealthIndicator.class)   
	@ConditionalOnLikeProperty(prefix="com.boot.jee.metrice",value="factory",likeValue="redis")
	@ConditionalOnProperty(prefix = "com.boot.jee.metrice", value = "enable", havingValue = "true", matchIfMissing = false) 
	public HealthIndicator getRedisHealthIndicator() {   
		return new RedisHealthIndicator();                                                                                                                                                                                                                                                            
    }  
	
	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnProperty(prefix = "com.boot.jee.metrice", value = "enable", havingValue = "true", matchIfMissing = false) 
	public EndpointHandlerMapping endpointHandlerMapping(ManagementServerProperties managementServerProperties,EndpointCorsProperties corsProperties,MvcEndpoints mvcEndpoints
			,ObjectProvider<List<EndpointHandlerMappingCustomizer>> provider) {
		Set<MvcEndpoint> endpoints = mvcEndpoints.getEndpoints();
		CorsConfiguration corsConfiguration = getCorsConfiguration(corsProperties);
		
		List<EndpointHandlerMappingCustomizer> providedCustomizers = provider
				.getIfAvailable();
		List<EndpointHandlerMappingCustomizer> mappingCustomizers = providedCustomizers == null
				? Collections.<EndpointHandlerMappingCustomizer>emptyList()
				: providedCustomizers;
				
		EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,
				corsConfiguration);
		mapping.setPrefix(managementServerProperties.getContextPath());
		MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(
				managementServerProperties.getSecurity().isEnabled(),
				managementServerProperties.getSecurity().getRoles());
		mapping.setSecurityInterceptor(securityInterceptor);
		for (EndpointHandlerMappingCustomizer customizer : mappingCustomizers) {
			customizer.customize(mapping);
		}
		return mapping;
	}
	
	@Bean
	@ConditionalOnMissingBean
	@ConditionalOnProperty(prefix = "com.boot.jee.metrice", value = "enable", havingValue = "false", matchIfMissing = false) 
	public EndpointHandlerMapping endpointHandlerMappingDis(ManagementServerProperties managementServerProperties,EndpointCorsProperties corsProperties,MvcEndpoints mvcEndpoints
			,ObjectProvider<List<EndpointHandlerMappingCustomizer>> provider) {
		Set<MvcEndpoint> endpoints = mvcEndpoints.getEndpoints();
		List<MvcEndpoint> remove = com.gitee.hermer.boot.jee.commons.collection.CollectionUtils.newArrayList();
		for (MvcEndpoint mvcEndpoint : endpoints) {
			if(mvcEndpoint instanceof HealthMvcEndpoint || mvcEndpoint instanceof MetricsMvcEndpoint){
				remove.add(mvcEndpoint);
			}
		}
		endpoints.removeAll(remove);
		CorsConfiguration corsConfiguration = getCorsConfiguration(corsProperties);
		
		List<EndpointHandlerMappingCustomizer> providedCustomizers = provider
				.getIfAvailable();
		List<EndpointHandlerMappingCustomizer> mappingCustomizers = providedCustomizers == null
				? Collections.<EndpointHandlerMappingCustomizer>emptyList()
				: providedCustomizers;
				
		EndpointHandlerMapping mapping = new EndpointHandlerMapping(endpoints,
				corsConfiguration);
		mapping.setPrefix(managementServerProperties.getContextPath());
		MvcEndpointSecurityInterceptor securityInterceptor = new MvcEndpointSecurityInterceptor(
				managementServerProperties.getSecurity().isEnabled(),
				managementServerProperties.getSecurity().getRoles());
		mapping.setSecurityInterceptor(securityInterceptor);
		for (EndpointHandlerMappingCustomizer customizer : mappingCustomizers) {
			customizer.customize(mapping);
		}
		return mapping;
	}
	
	private CorsConfiguration getCorsConfiguration(EndpointCorsProperties properties) {
		if (CollectionUtils.isEmpty(properties.getAllowedOrigins())) {
			return null;
		}
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(properties.getAllowedOrigins());
		if (!CollectionUtils.isEmpty(properties.getAllowedHeaders())) {
			configuration.setAllowedHeaders(properties.getAllowedHeaders());
		}
		if (!CollectionUtils.isEmpty(properties.getAllowedMethods())) {
			configuration.setAllowedMethods(properties.getAllowedMethods());
		}
		if (!CollectionUtils.isEmpty(properties.getExposedHeaders())) {
			configuration.setExposedHeaders(properties.getExposedHeaders());
		}
		if (properties.getMaxAge() != null) {
			configuration.setMaxAge(properties.getMaxAge());
		}
		if (properties.getAllowCredentials() != null) {
			configuration.setAllowCredentials(properties.getAllowCredentials());
		}
		return configuration;
	}

}
